diff --git a/src/lib/drivers/magnetometer/CMakeLists.txt b/src/lib/drivers/magnetometer/CMakeLists.txt
index 198fea075cb4ae42cc7ab365a84a4d74b86e5138..49b0cd0ad08b660c453d4639cc9a4996a011efc0 100644
--- a/src/lib/drivers/magnetometer/CMakeLists.txt
+++ b/src/lib/drivers/magnetometer/CMakeLists.txt
@@ -31,4 +31,4 @@
 #
 ############################################################################
 
-px4_add_library(drivers__magnetometer PX4Magnetometer.cpp)
+px4_add_library(drivers_magnetometer PX4Magnetometer.cpp)
diff --git a/src/lib/drivers/magnetometer/PX4Magnetometer.cpp b/src/lib/drivers/magnetometer/PX4Magnetometer.cpp
index f75de60e987494a1e2280c7a42c2ecf9a7f3469b..d6d33e0575d6a53616335aed5f6534565cced7af 100644
--- a/src/lib/drivers/magnetometer/PX4Magnetometer.cpp
+++ b/src/lib/drivers/magnetometer/PX4Magnetometer.cpp
@@ -34,118 +34,100 @@
 
 #include "PX4Magnetometer.hpp"
 
-PX4Magnetometer::PX4Magnetometer(const char *path, device::Device  *interface, uint8_t dev_type, enum Rotation rotation,
-				 float scale) :
-	CDev(path),
-	_interface(interface)
-{
-	_device_id.devid = _interface->get_device_id();
-	// _device_id.devid_s.bus_type = (device::Device::DeviceBusType)_interface->get_device_bus_type();
-	// _device_id.devid_s.bus = _interface->get_device_bus();
-	// _device_id.devid_s.address = _interface->get_device_address();
-	_device_id.devid_s.devtype = dev_type;
-
-	CDev::init();
+#include <lib/drivers/device/Device.hpp>
 
+PX4Magnetometer::PX4Magnetometer(uint32_t device_id, uint8_t priority, enum Rotation rotation) :
+	CDev(nullptr),
+	_sensor_mag_pub{ORB_ID(sensor_mag), priority},
+	_rotation{rotation}
+{
 	_class_device_instance = register_class_devname(MAG_BASE_DEVICE_PATH);
 
-	_rotation = rotation;
-	_scale = scale;
+	_sensor_mag_pub.get().device_id = device_id;
+	_sensor_mag_pub.get().scaling = 1.0f;
 
-	_cal.x_offset = 0;
-	_cal.x_scale  = 1.0f;
-	_cal.y_offset = 0;
-	_cal.y_scale  = 1.0f;
-	_cal.z_offset = 0;
-	_cal.z_scale  = 1.0f;
+	// force initial publish to allocate uORB buffer
+	// TODO: can be removed once all drivers are in threads
+	_sensor_mag_pub.update();
 }
 
 PX4Magnetometer::~PX4Magnetometer()
 {
-	if (_topic != nullptr) {
-		orb_unadvertise(_topic);
-	}
-}
-
-int PX4Magnetometer::init()
-{
-	mag_report report{};
-	report.device_id = _device_id.devid;
-
-	if (_topic == nullptr) {
-		_topic = orb_advertise_multi(ORB_ID(sensor_mag), &report, &_orb_class_instance, ORB_PRIO_HIGH - 1);
-
-		if (_topic == nullptr) {
-			PX4_ERR("Advertise failed.");
-			return PX4_ERROR;
-		}
+	if (_class_device_instance != -1) {
+		unregister_class_devname(MAG_BASE_DEVICE_PATH, _class_device_instance);
 	}
-
-	return PX4_OK;
 }
 
 int PX4Magnetometer::ioctl(cdev::file_t *filp, int cmd, unsigned long arg)
 {
 	switch (cmd) {
-	case MAGIOCSSCALE:
-		// Copy scale in.
-		memcpy(&_cal, (struct mag_calibration_s *) arg, sizeof(_cal));
-		return OK;
+	case MAGIOCSSCALE: {
+			// Copy offsets and scale factors in
+			mag_calibration_s cal{};
+			memcpy(&cal, (mag_calibration_s *) arg, sizeof(cal));
+
+			_calibration_offset = matrix::Vector3f{cal.x_offset, cal.y_offset, cal.z_offset};
+			_calibration_scale = matrix::Vector3f{cal.x_scale, cal.y_scale, cal.z_scale};
+		}
 
-	case MAGIOCGSCALE:
-		// Copy scale out.
-		memcpy((struct mag_calibration_s *) arg, &_cal, sizeof(_cal));
-		return OK;
+		return PX4_OK;
 
 	case DEVIOCGDEVICEID:
-		return _device_id.devid;
+		return _sensor_mag_pub.get().device_id;
 
 	default:
-		// Give it to the superclass.
-		return CDev::ioctl(filp, cmd, arg);
+		return -ENOTTY;
 	}
 }
 
-void PX4Magnetometer::configure_filter(float sample_freq, float cutoff_freq)
+void PX4Magnetometer::set_device_type(uint8_t devtype)
 {
-	_filter_x.set_cutoff_frequency(sample_freq, cutoff_freq);
-	_filter_y.set_cutoff_frequency(sample_freq, cutoff_freq);
-	_filter_z.set_cutoff_frequency(sample_freq, cutoff_freq);
+	// current DeviceStructure
+	union device::Device::DeviceId device_id;
+	device_id.devid = _sensor_mag_pub.get().device_id;
+
+	// update to new device type
+	device_id.devid_s.devtype = devtype;
+
+	// copy back to report
+	_sensor_mag_pub.get().device_id = device_id.devid;
 }
 
-// @TODO: use fixed point math to reclaim CPU usage
-int PX4Magnetometer::publish(float x, float y, float z, float temperature)
+void PX4Magnetometer::update(hrt_abstime timestamp, int16_t x, int16_t y, int16_t z)
 {
-	sensor_mag_s report{};
+	sensor_mag_s &report = _sensor_mag_pub.get();
+	report.timestamp = timestamp;
 
-	report.device_id   = _device_id.devid;
-	report.error_count = 0;
-	report.scaling 	   = _scale;
-	report.timestamp   = hrt_absolute_time();
-	report.temperature = temperature;
-	report.is_external = false;
+	// Apply rotation (before scaling)
+	float xraw_f = x;
+	float yraw_f = y;
+	float zraw_f = z;
+	rotate_3f(_rotation, xraw_f, yraw_f, zraw_f);
 
+	// Apply range scale and the calibrating offset/scale
+	const matrix::Vector3f val_calibrated{(((matrix::Vector3f{xraw_f, yraw_f, zraw_f} * report.scaling) - _calibration_offset).emult(_calibration_scale))};
 
 	// Raw values (ADC units 0 - 65535)
 	report.x_raw = x;
 	report.y_raw = y;
 	report.z_raw = z;
 
-	// Apply the rotation.
-	rotate_3f(_rotation, x, y, z);
+	report.x = val_calibrated(0);
+	report.y = val_calibrated(1);
+	report.z = val_calibrated(2);
 
-	// Apply FS range scale and the calibrating offset/scale
-	x = ((x * _scale) - _cal.x_offset) * _cal.x_scale;
-	y = ((y * _scale) - _cal.y_offset) * _cal.y_scale;
-	z = ((z * _scale) - _cal.z_offset) * _cal.z_scale;
+	poll_notify(POLLIN);
+	_sensor_mag_pub.update();
+}
 
-	// Filtered values
-	report.x = _filter_x.apply(x);
-	report.y = _filter_y.apply(y);
-	report.z = _filter_z.apply(z);
+void PX4Magnetometer::print_status()
+{
+	PX4_INFO(MAG_BASE_DEVICE_PATH " device instance: %d", _class_device_instance);
 
-	poll_notify(POLLIN);
-	orb_publish(ORB_ID(sensor_mag), _topic, &report);
+	PX4_INFO("calibration scale: %.5f %.5f %.5f", (double)_calibration_scale(0), (double)_calibration_scale(1),
+		 (double)_calibration_scale(2));
+	PX4_INFO("calibration offset: %.5f %.5f %.5f", (double)_calibration_offset(0), (double)_calibration_offset(1),
+		 (double)_calibration_offset(2));
 
-	return PX4_OK;
-}
\ No newline at end of file
+	print_message(_sensor_mag_pub.get());
+}
diff --git a/src/lib/drivers/magnetometer/PX4Magnetometer.hpp b/src/lib/drivers/magnetometer/PX4Magnetometer.hpp
index 2dff3c20c48a3f70b9d5007831c99ca6372b8650..00f004965cc02909b22313f5d2f01cf73805cd0d 100644
--- a/src/lib/drivers/magnetometer/PX4Magnetometer.hpp
+++ b/src/lib/drivers/magnetometer/PX4Magnetometer.hpp
@@ -31,51 +31,42 @@
  *
  ****************************************************************************/
 
-
-#include <mathlib/math/filter/LowPassFilter2p.hpp>
-
-#include <drivers/device/integrator.h>
 #include <drivers/drv_mag.h>
 #include <drivers/drv_hrt.h>
-#include <lib/drivers/device/Device.hpp>
 #include <lib/cdev/CDev.hpp>
 #include <lib/conversion/rotation.h>
-#include <uORB/topics/sensor_mag.h>
 #include <uORB/uORB.h>
+#include <uORB/Publication.hpp>
+#include <uORB/topics/sensor_mag.h>
 
 class PX4Magnetometer : public cdev::CDev
 {
 
 public:
-	PX4Magnetometer(const char *name, device::Device  *interface, uint8_t dev_type, enum Rotation rotation, float scale);
+	PX4Magnetometer(uint32_t device_id, uint8_t priority, enum Rotation rotation);
 	~PX4Magnetometer() override;
 
-	int	init() override;
 	int	ioctl(cdev::file_t *filp, int cmd, unsigned long arg) override;
 
-	int publish(float x, float y, float z, float temperature);
+	void set_device_type(uint8_t devtype);
+	void set_error_count(uint64_t error_count) { _sensor_mag_pub.get().error_count = error_count; }
+	void set_scale(float scale) { _sensor_mag_pub.get().scaling = scale; }
+	void set_temperature(float temperature) { _sensor_mag_pub.get().temperature = temperature; }
+	void set_external(bool external) { _sensor_mag_pub.get().is_external = external; }
 
-	void configure_filter(float sample_freq, float cutoff_freq);
+	void update(hrt_abstime timestamp, int16_t x, int16_t y, int16_t z);
 
-private:
-	// Pointer to the communication interface
-	const device::Device *_interface{nullptr};
-
-	mag_calibration_s _cal{};
+	void print_status();
 
-	orb_advert_t _topic{nullptr};
-
-	device::Device::DeviceId _device_id{};
+private:
 
-	int	_orb_class_instance{-1};
+	uORB::Publication<sensor_mag_s>	_sensor_mag_pub;
 
-	int _class_device_instance{-1};
+	const enum Rotation	_rotation;
 
-	enum Rotation _rotation {ROTATION_NONE};
+	matrix::Vector3f	_calibration_scale{1.0f, 1.0f, 1.0f};
+	matrix::Vector3f	_calibration_offset{0.0f, 0.0f, 0.0f};
 
-	float _scale{1.0f};
+	int			_class_device_instance{-1};
 
-	math::LowPassFilter2p _filter_x{100, 20};
-	math::LowPassFilter2p _filter_y{100, 20};
-	math::LowPassFilter2p _filter_z{100, 20};
 };